package com.coderman.common.starter.logparam.aspect;



import com.coderman.common.starter.logparam.annotations.RequestLogic;
import com.coderman.common.starter.logparam.beans.RequestLogicBean;
import com.coderman.common.starter.logparam.context.RequestBusLogicContext;
import com.coderman.common.starter.logparam.service.logparams.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * Created by 58-daojia on 2018-9-19.
 *
 * @author: fanchunshuai
 * @version: V1.0
 * @Desc: 接口方法耗时统计
 */
@Aspect
@Component
@Order(value = 2)
public class RequestLogicExeTimeAspect {
    @Resource
    private RequestBusLogicContext baseBusLogicContext;

    @Resource
    private LogService logService;

    /**
     * 方法执行的时间监控
     * 可有问题？？？？
     * ThreadLocal了解一下，哈哈
     * private Map<Integer, Long> methodExeTimeMap = new HashMap<>(256);
     * <p>
     * concurrentHashMap??可以吗
     */
    private static final ThreadLocal<Long> localStartUseTime = new ThreadLocal<>();


    /**
     * 在接口方法执行之前记录开始时间
     *
     * @throws Throwable
     */
    @Before("@annotation(requestLogic)")
    public void exeTimeStart(JoinPoint joinPoint, RequestLogic requestLogic) throws Throwable {

        //获取key
        String key = baseBusLogicContext.getHashKey(joinPoint);
        RequestLogicBean baseBusLogicBean = baseBusLogicContext.getLogicBean(key);
        if (baseBusLogicBean == null) {
            return;
        }
        //如果需要记录方法执行时间
        if (baseBusLogicBean.isExeTime() == true) {
            localStartUseTime.set(System.currentTimeMillis());
        }
        //如果需要打印入参
        if (baseBusLogicBean.isLogInParam() == true) {
            logService.logInputParam(joinPoint.getArgs(),baseBusLogicContext.getTmpKey(joinPoint));
        }
    }


    /**
     * 在接口方法执行之后录开始时间
     *
     * @throws Throwable
     */
    @AfterReturning(value = "@annotation(requestLogic)", returning = "returnValue")
    public void exeTimeEnd(JoinPoint joinPoint,RequestLogic requestLogic,Object returnValue) throws Throwable {
        long endTime = System.currentTimeMillis();

        String key = baseBusLogicContext.getHashKey(joinPoint);
        //获取key
        RequestLogicBean baseBusLogicBean = baseBusLogicContext.getLogicBean(key);
        if (baseBusLogicBean == null) {
            return;
        }
        String newKey = getNewKey(key);
        //如果需要记录方法执行时间
        if (baseBusLogicBean.isExeTime() == true) {
            long startTime = localStartUseTime.get();
            logService.logExeTime(newKey, (endTime - startTime), "");
            //防止内存溢出，用完需要及时remove掉
            localStartUseTime.remove();
        }
        //如果需要打印出参
        if (baseBusLogicBean.isLogOutParam() == true) {
            //记录出参
            logService.logOutputParam(returnValue, newKey, "");
        }
    }

    private String getNewKey(String key) {
        String tmpKey = key;
        String methodStr = tmpKey.substring(tmpKey.lastIndexOf("."));
        String methodStr2 = tmpKey.replace(methodStr, "");
        return methodStr2.substring(methodStr2.lastIndexOf(".") + 1) + methodStr;
    }


}